package com.cy.jt.sercurity.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
/**
 * 说明:学框架首先要学的就是规范,规则.
 * 定义UserDetailsService接口的具体实现,在这个实现定义用户登录逻辑
 */
@Service
public class UserDetailServiceImpl implements UserDetailsService {
    /*
    * @Autowired注解描述属性时,注入规则是怎样的?
    * spring框架会依据@Autow注解描述的属性类型,从spring容器中查找对应的Bean
    * ,假如子找到一个则直接注入,假如找到多个还会比对属性名是否与容器中的Bean的
    * 名字有相同的,有则直接注入,没有则抛出异常
    * */
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    /*
     * 当我们登陆操作时,底层会通过过滤器登对象,调用这个方法
     * @param username 这个参数为页面输出的用户名
     * @return 一般时从数据库基于用户名查询到的用户信息
     * 定义UserDetailsService接口的具体的实现,在这个实现定义用户登陆逻辑
     * */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1.基于用户名从数据库查询用户信息
        if (!"jack".equals(username))throw new UsernameNotFoundException("user not exists");
        //2.将用户信息进行封装到UserDetailsService对象中并返回
        //假设这个密码是从数据库查询出来的
        String encodedPwd = passwordEncoder.encode("123456");
        System.out.println(encodedPwd);
        //假设这个权限信息也是从数据库查询到的
        //假设分配权限的方式是角色,编写字符串是用"ROLE_
        List<GrantedAuthority> grantedAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList
                ("ROLE_admin,ROLE_normal,sys:res:retrieve,sys:res:create");
        User user = new User(username,encodedPwd,grantedAuthorities);
        return user;
    }
}
